#include "Parser.h"
#include "util/logger/Logger.h"
#include "util/logger/LoggerManager.h"
#include "util/StringUtils.h"

namespace parser {
Parser::Parser(Rule* rule) {
	this->file = NULL;
	this->rule = rule;
}

Parser::~Parser() {
	if (this->file != NULL) {
		delete this->file;
	}
}

Parser* Parser::setFileName(std::string fileName) {
	if (this->file != NULL) {
		delete this->file;
	}
	this->file = new util::File(fileName);
	return this;
}

ParsedData* Parser::processNextLine() throw (util::IOException,
		InvalidDataException) {
	util::Logger * logger = util::LoggerManager::getInstance()->getLogger();
	std::string line;
	if (!(this->file->isOpen())) {
		this->file->openFileReadOnly();
	}
	line = this->file->readLine();
	// Saco el enter que lee del final el readline
	char lineSeparator = '\r';
	if (line[line.size() - 1] == lineSeparator) {
		line = line.substr(0, line.length() - 1);
	}
	std::string::iterator it;
	std::string buff;
	logger->info("Parseando linea " + this->getStrLineNumber()
			+ " del archivo \"" + this->file->getFileName() + "\".");
	try {
		for (it = line.begin(); it < line.end(); it++) {
			char c = *it;
			if (c != this->rule->getDataSeparator()) {
				buff += c;
			} else {
				logger->info("Agregando el valor: \"" + buff + "\"");
				this->addValueToRule(buff);
				buff = "";
			}
		}
		if (buff != "") {
			logger->info("Agregando el valor: \"" + buff + "\"");
			this->addValueToRule(buff);
		}
	} catch (util::Exception &e) {
		this->rule->discardCurrentParsedData();
		throw ;
	}
	logger->info("Parseo de linea completa.");
	return this->rule->getParsedData(true);
}

bool Parser::noMoreDataInFile() throw (util::IOException) {
	if (this->file != NULL) {
		return this->file->endOfFile();
	} else {
		throw(util::IOException("No se puede acceder al archivo \"" + this->file->getFileName() + "\"."));
	}
}

std::string Parser::getFileName() {
	return this->file->getFileName();
}

std::string Parser::getStrLineNumber() {
	return util::intToString(this->file->getCurrentLineNumber());
}

void Parser::addValueToRule(std::string value) throw (InvalidDataException) {
	util::Logger * logger = util::LoggerManager::getInstance()->getLogger();
	util::trim(value);
	this->rule->addValue(value);
}

}
